package com.atxiaodei.nio.nioday01;

import org.junit.Test;

import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;
import java.util.stream.Collectors;

/**
 * @author wangmeng
 * @date 2020/9/12
 *
 * .Stream的filter与谓语逻辑
 **/
public class StreamApi3 {
    List<StreamTestVo> list = Arrays.asList(
            new StreamTestVo(1, 23, "M", "Rick", "Beethovan"),
            new StreamTestVo(2, 13, "F", "Martina", "Hengis"),
            new StreamTestVo(3, 43, "M", "Ricky", "Martin"),
            new StreamTestVo(4, 26, "M", "Jon", "Lowman"),
            new StreamTestVo(5, 19, "F", "Cristine", "Maria"),
            new StreamTestVo(6, 15, "M", "David", "Feezor"),
            new StreamTestVo(7, 68, "F", "Melissa", "Roy"),
            new StreamTestVo(8, 79, "M", "Alex", "Gussin"),
            new StreamTestVo(9, 15, "F", "Neetu", "Singh"),
            new StreamTestVo(10, 45, "M", "Naveen", "Jain")
    );
    @Test
    public void test1(){

        // 取出集合中年龄大于70岁的人，并且是男性的
        // ① 匿名内部类 不求快 只求一次完整理解
        list.stream()
                .filter(x->x.getAge() >70&& "M".equals(x.getGender()))
                .collect(Collectors.toList())
                .forEach(System.out::println);
        List<StreamTestVo> collect = list.stream()
                .filter(new Predicate<StreamTestVo>() {
                    @Override
                    public boolean test(StreamTestVo streamTestVo) {
                        return streamTestVo.getAge() > 70 && "M".equals(streamTestVo.getGender());
                    }
                }).collect(Collectors.toList());
        System.out.println(collect);
        System.out.println("---------------------------------------------------");
        // ②lamdba 表达式取
        System.out.println("---------------------------------------------------");
        // ③ 谓语逻辑去，详情test3方法
    }

    @Test
    public void test2(){
        // 我们已经知道lambda表达式表达的是一个匿名接口函数的实现。那具体到Stream.filter()中，它表达的是什么呢？
        // 可以看出它表达的是一个Predicate接口，在英语中这个单词的意思是：谓词。
        /**
         * 什么是谓词逻辑？
         * WHERE 和 AND 限定了主语employee是什么，那么WHERE和AND语句所代表的逻辑就是谓词逻辑
         *
         * SELECT *
         * FROM employee
         * WHERE age > 70
         * AND gender = 'M'
         *
         * 通常情况下，filter函数中lambda表达式为一次性使用的谓词逻辑。如果我们的谓词逻辑需要被多处、多场景、多代码中使用，
         * 通常将它抽取出来单独定义到它所限定的主语实体中。
         * 比如：将下面的谓词逻辑定义在Employee实体class中。
         *
         *    public static Predicate<Employee> ageGreaterThan70 = x -> x.getAge() >70;
         *    public static Predicate<Employee> genderM = x -> x.getGender().equals("M");
         */
        // and 语法
        list.stream()
                .filter(StreamTestVo.ageGreaterThan70.and(StreamTestVo.genderM))
                .collect(Collectors.toList())
                .forEach(System.out::println);

        System.out.println("-------------------------------------------------------------");
        // or 语法 实际上就是年龄大于70的和所有的男性（由于79的那位也是男性，所以就是所有的男性）
        list.stream()
                .filter(StreamTestVo.ageGreaterThan70.or(StreamTestVo.genderM))
                .forEach(System.out::println);

        System.out.println("-------------------------------------------------------------");
        // negate语法（取反）上述or语法取反 实际上就是所有的女性信息
        list.stream()
                .filter(StreamTestVo.ageGreaterThan70.or(StreamTestVo.genderM).negate())
                .forEach(System.out::println);

    }
}
